package com.atguigu.srb.core.service.impl;

import com.atguigu.srb.core.enums.TransTypeEnum;
import com.atguigu.srb.core.hfb.FormHelper;
import com.atguigu.srb.core.hfb.HfbConst;
import com.atguigu.srb.core.hfb.RequestHelper;
import com.atguigu.srb.core.mapper.*;
import com.atguigu.srb.core.pojo.entity.*;
import com.atguigu.srb.core.pojo.vo.InvestVO;
import com.atguigu.srb.core.service.*;
import com.atguigu.srb.core.utils.LendNoUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 标的出借记录表 服务实现类
 * </p>
 *
 * @author AtLong
 * @since 2022-06-11
 */
@Service
@Slf4j
public class LendItemServiceImpl extends ServiceImpl<LendItemMapper, LendItem> implements LendItemService {
    @Resource
    LendItemMapper lendItemMapper;
    @Resource
    UserAccountService userAccountService;
    @Resource
    UserBindService userBindService;
    @Resource
    LendService lendService;
    @Resource
    UserInfoService userInfoService;
    @Resource
    TransFlowService transFlowService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String commitInvest(InvestVO investVO) {
        // 获取前端参数=======================
        Long lendId = investVO.getLendId(); // 标的表主键id
        Long investUserId = investVO.getInvestUserId();   // 投资人的id
        String investName = investVO.getInvestName();     // 投资人姓名
        String investAmount = investVO.getInvestAmount(); //投资金额
        // 获取当前标的对象
        Lend lend = lendService.getById(lendId);
        // 获取用户投资人信息
        UserInfo investUserInfo = userInfoService.getById(investUserId);
        // 获取借款人信息
        UserInfo borrowUserInfo = userInfoService.getById(lend.getUserId());

        //在商户平台中生成投资信息==========================================
        //标的下的投资信息
        LendItem lendItem = new LendItem();
        lendItem.setLendItemNo(LendNoUtils.getLendItemNo());
        lendItem.setLendId(lendId);
        lendItem.setInvestUserId(investUserId);
        lendItem.setInvestName(investUserInfo.getName());
        lendItem.setInvestAmount(new BigDecimal(investAmount));
        lendItem.setLendYearRate(lend.getLendYearRate());
        lendItem.setInvestTime(LocalDateTime.now());
        lendItem.setLendStartDate(lend.getLendStartDate());
        lendItem.setLendEndDate(lend.getLendEndDate());
        lendItem.setStatus(0);
        // 预期收益
        BigDecimal expectAmountForItem = lendService.getInterestCount(
                lendItem.getInvestAmount(), lendItem.getLendYearRate(),
                lend.getPeriod(), lend.getReturnMethod());
        lendItem.setExpectAmount(expectAmountForItem);
        // 实际收益
        lendItem.setRealAmount(new BigDecimal(0));
        lendItemMapper.insert(lendItem);

        HashMap<String, Object> paramMap = new HashMap<>();
        String url = HfbConst.INVEST_URL;                           // 联调地址
        paramMap.put("agentId", HfbConst.AGENT_ID);                 // 给商户分配的唯一标识
        paramMap.put("voteBindCode", investUserInfo.getBindCode());  // 投资人绑定协议号
        paramMap.put("benefitBindCode", borrowUserInfo.getBindCode());  // 借款人绑定协议号。
        paramMap.put("agentProjectCode", lend.getLendNo());           // 项目编号。只能由数字、字母组成。
        paramMap.put("agentProjectName", lend.getTitle());          // 项目名称
        paramMap.put("agentBillNo", LendNoUtils.getLendItemNo());    //商户订单号
        paramMap.put("voteAmt", investAmount);                       // 投资金额投
        paramMap.put("votePrizeAmt", 0);                       // 资奖励金额。
        paramMap.put("voteFeeAmt", 0);                         // 商户手续费。最多小数点后两
        paramMap.put("projectAmt", lend.getAmount());           // 项目总金额。用来控制项目投标总金额。
        paramMap.put("note", "消费快乐");                        // 投资备注
        paramMap.put("returnUrl", HfbConst.INVEST_RETURN_URL);    // 异步通商户投资处理结果的完整地址
        paramMap.put("notifyUrl", HfbConst.INVEST_NOTIFY_URL);    // 同步返回商户的完整地址
        paramMap.put("timestamp", RequestHelper.getTimestamp());    // 时间戳。
        paramMap.put("sign", RequestHelper.getSign(paramMap));      // 验签参数
        // 生成表单
        String formStr = FormHelper.buildForm(url, paramMap);
        log.info("标的出借记录表投资生成表单---->" + formStr);
        return formStr;
    }

    /***异步回调
     * （1）账户金额更改（剩余金额和冻结金额）
     * （2）新增投资状态（lend_item表中的status）
     * （3）更新标的信息（lend表中的投资人数和已投金额）
     * （4）添加交易流水
     * @param paramMap
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String asyncNotifyLendItem(Map<String, Object> paramMap) {
        // ====获取paramMap回调参数=====
        //判断交易流水是否存在
        String agentBillNo = (String) paramMap.get("agentBillNo");
        if (transFlowService.isSaveTransFlow(agentBillNo)) {
            log.warn("幂等性返回");
            return "fail";
        }
        String voteBindCode = (String) paramMap.get("voteBindCode");
        //======（1）账户金额更改（剩余金额和冻结金额）=======
        userAccountService.updateUserAccountAmountAndFreezeAmount(paramMap);
        //======（2）新增投资状态（lend_item表中的status）=======
        this.updateLendItemStatus(voteBindCode);
        //======= (3) 更新标的信息（lend表中的投资人数和已投金额）=======
        lendService.updateLendInvestNumAndInvestAmount(voteBindCode);
        //========（4）添加交易流水========
        transFlowService.saveTransFlow(paramMap);
        return "success";
    }

    @Override
    public void updateLendItemStatus(String voteBindCode) {
        QueryWrapper<UserBind> userBindQueryWrapper = new QueryWrapper<>();
        userBindQueryWrapper.eq("bind_code", voteBindCode);
        UserBind voteUserBind = userBindService.getOne(userBindQueryWrapper);
        QueryWrapper<LendItem> lendItemQueryWrapper = new QueryWrapper<>();
        lendItemQueryWrapper.eq("invest_user_id", voteUserBind.getUserId()).ne("statue",1);
       // lendItemMapper.selectList()
        LendItem lendItem = lendItemMapper.selectOne(lendItemQueryWrapper);
        lendItem.setStatus(1);
        lendItemMapper.update(lendItem, lendItemQueryWrapper);
    }

    @Override
    public List<LendItem> selectLendItemListByLendIdWithStatus(Long lendId, Integer status) {
        QueryWrapper<LendItem> lendItemQueryWrapper = new QueryWrapper<>();
        lendItemQueryWrapper.eq("lend_id", lendId).eq("status", status);
        List<LendItem> lendItemList = lendItemMapper.selectList(lendItemQueryWrapper);
        return lendItemList;
    }


}
